package com.xiaoq.coms.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;

import com.springcryptoutils.core.digest.DigesterImpl;
import com.springcryptoutils.core.digest.DigesterImpl.OutputMode;

public class DigestUtil {
	private static final String UTF8 = "UTF-8";
	
	public static String md5(String s, String cs) {
		DigesterImpl di = new DigesterImpl();
		di.setAlgorithm("MD5");
		di.setOutputMode(OutputMode.HEX);
		di.setCharsetName(cs);
		try {
			di.afterPropertiesSet();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		}
		return di.digest(s);
	}
	
	public static String md5(String s) {
		return md5(s, UTF8);
	}
	
	public static String md5AsString(byte[] b) {
		byte[] res = md5AsByte(b);
		return HexUtil.hex(res);
	}
	
	public static String md5AsStringByFile(File file) {
		FileInputStream ins = null;
		try {
			ins = new FileInputStream(file);
	        MessageDigest md5 = MessageDigest.getInstance("MD5");
	        byte[] buffer = new byte[1024];
            int numOfBytesRead;
            while( (numOfBytesRead = ins.read(buffer)) > 0){
                md5.update(buffer, 0, numOfBytesRead);
            }
	        BigInteger bi = new BigInteger(1, md5.digest());
	        return bi.toString(16).toUpperCase();
	    } catch (Exception e) {
	        e.printStackTrace();
	    } finally {
            if(null != ins) {
                try {
	                ins.close();
	            } catch (IOException e) {
	                e.printStackTrace();
	            }
	        }
	    }
		return "";
	}
	
	public static String md5AsStringByFile(String filePath) {
		File file = new File(filePath);
		if (!file.exists()) {
			throw new RuntimeException("file not found, " + filePath);
		}
		if (!file.canRead()) {
			throw new RuntimeException("file not readable, " + filePath);
		}
		return md5AsStringByFile(file);
	}
	
	public static byte[] hash(byte[] b, String argo) {
		DigesterImpl di = new DigesterImpl();
		di.setAlgorithm(argo);
		try {
			di.afterPropertiesSet();
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (NoSuchProviderException e) {
			e.printStackTrace();
		}
		return di.digest(b);
	}
	
	public static byte[] md5AsByte(byte[] b) {
		return hash(b, "MD5");
	}
	
	public static byte[] sha256(byte[] b) {
		return hash(b, "SHA256");
	}
	
	public static void main(String[] args) throws Exception {
		String str = "hello";
		byte[] b  = "hello".getBytes("UTF-8");
		System.out.println(DigestUtil.md5(str));
		System.out.println(DigestUtil.md5AsByte(b));
		System.out.println(DigestUtil.md5AsString(b));
		
		long nonce = 0;
		String hashHex = null;
		while (true) {
			hashHex = DigestUtil.md5AsString(("blockchain" + nonce).getBytes());
			if (hashHex.startsWith("000000")) {
				System.out.println(hashHex);
				System.out.println(nonce);
				break;
			}
			nonce++;
		}
	}
}
